package com.jian.sys.Realm;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jian.sys.common.ActiverUser;
import com.jian.sys.common.Constant;
import com.jian.sys.common.UserGetPermission;
import com.jian.sys.pojo.Permission;
import com.jian.sys.pojo.User;
import com.jian.sys.service.PermissionService;
import com.jian.sys.service.RoleService;
import com.jian.sys.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class UserRealm extends AuthorizingRealm {
    @Autowired
    @Lazy //懒加载 只有使用才会生效
    UserService userService;
    @Autowired
    @Lazy
    RoleService roleService;
    @Autowired
    @Lazy
    PermissionService permissionService;
    public String getName(){
        return this.getClass().getSimpleName();
    }

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //获取当前认证的用户
        ActiverUser activerUser= (ActiverUser) principalCollection.getPrimaryPrincipal();
        //获取当前的用户
        User user=activerUser.getUser();
        //获取当前用户的所有权限
        List<String> permissions=activerUser.getPermissions();
        //判断用户的类型 如果是超级管理员拥有所有权限
        if(user.getType()== Constant.USER_TYPE_SUPER){
            //添加权限 所有权限
            info.addStringPermission("*:*");
        }else{
            //添加权限 所拥护的权限
            info.addStringPermissions(permissions);
        }

        return info;
    }

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("loginname",token.getPrincipal().toString());
        User user = userService.getOne(wrapper);
        if(null!=user){
            ActiverUser activerUser = new ActiverUser();
            activerUser.setUser(user);
            //获取权限 设置权限认证
            Integer currentUserId=user.getId();
            List<Permission> list=null;
            //获取用户的角色ID
            List<Integer>roleIds=this.userService.queryUserRoleByUid(currentUserId);
            //通过角色ID获取权限和菜单
            Set<Integer> pIds=new HashSet<>();
            for (Integer roleId : roleIds) {
                List<Integer> permissionId=this.roleService.queryRolePermissionByRid(roleId);
                for (Integer pid : permissionId) {
                    pIds.add(pid);
                }
            }
            if (pIds.size()>0){
                QueryWrapper<Permission> qw = new QueryWrapper<>();
                qw.in("id",pIds);
                qw.eq("type",Constant.TYPE_PERMISSION);
                qw.eq("available",Constant.AVAILABLE_TRUE);

                list = this.permissionService.list(qw);
                System.out.println(list);
            }else {
                list =new ArrayList<>();
            }
            List<String> percodes=new ArrayList<>();
            for (Permission permission : list) {
                //获取权限码
                percodes.add(permission.getPercode());
            }
            //设置认证权限码
            activerUser.setPermissions(percodes);

            //UUID生成的盐值 后面添加用户需要UUID生成添加进去
            ByteSource salt =ByteSource.Util.bytes(user.getSalt());
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activerUser,user.getPwd(),salt,this.getName());
            return info;
        }
        return null;
    }
}
